﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ObviousCode.UI.Aspect.PluginLibrary.Interfaces;
using ObviousCode.Common.Utils.UI.Bounds;
using ObviousCode.Common.Utils;
using System.Drawing;
using ObviousCode.Aspect.PluginLibrary.StateHandler;
using ObviousCode.Aspect.PluginLibrary.Interfaces;

namespace ObviousCode.Aspect.PluginLibrary.Collections
{
    public class AspectChartObjectCollection
    {
        List<ISurfaceObject> _items;
        List<ISurfaceRelationship> _relationships;

        BoundsRegistry<ISurfaceObject> _bounds;

        public AspectChartObjectCollection()
        {
            _items = new List<ISurfaceObject>();
            _relationships = new List<ISurfaceRelationship>();
            _bounds = new BoundsRegistry<ISurfaceObject>();
        }

        public void ClearBounds()
        {
            _bounds.Clear();
        }

        public void Add(ISurfaceObject item)
        {
            if (_items.Count(p => p.InstanceKey == item.InstanceKey) > 0) return;

            item.SelectionStateChanged += new EventHandler(item_SelectionStateChanged);
            _items.Add(item);

            FireCollectionChangedEvent();
        }        

        public void Add(ISurfaceRelationship relationship)
        {          
            _relationships.Add(relationship);

            FireCollectionChangedEvent();        
        }        

        public void RegisterItemBounds(ISurfaceObject item, System.Drawing.RectangleF bounds)
        {
            _bounds.Register(bounds, item);
        }

        public IEnumerable<ISurfaceObject> Items
        {
            get
            {
                foreach (ISurfaceObject plugin in _items)
                {
                    yield return plugin;
                }
            }
        }

        public IEnumerable<ISurfaceRelationship> Relationships
        {
            get
            {
                foreach (ISurfaceRelationship relationship in _relationships)
                {
                    yield return relationship;
                }
            }
        }

        
        public ISurfaceObject ItemAt(Point point)
        {
            return _bounds.GetItemForPointF(new PointF((float)point.X, (float)point.Y));
        }

        public ISurfaceObject ItemAt(PointF point)
        {
            return _bounds.GetItemForPointF(point);
        }

        public void ItemDragStarted(ISurfaceObject iAspectPlugin)
        {
            foreach (ISurfaceObject plugin in _items.Where(p => (p.State == BaseItemState.Selected && p.InstanceKey != iAspectPlugin.InstanceKey)))
            {
                plugin.BeginAffinativeDrag();
            }
        }

        public void ItemDragging(ISurfaceObject iAspectPlugin, PointF pointF)
        {
            foreach (ISurfaceObject plugin in _items.Where(p => (p.IsInAffinativeDrag && p.InstanceKey != iAspectPlugin.InstanceKey)))
            {
                plugin.ContinueAffinativeDrag(pointF);
            }
        }

        public void ItemDragCompleted(ISurfaceObject iAspectPlugin)
        {
            foreach (ISurfaceObject plugin in _items.Where(p => (p.IsInAffinativeDrag && p.InstanceKey != iAspectPlugin.InstanceKey)))
            {
                plugin.EndAffinativeDrag();
            }
        }

        public bool IsDragging
        {
            get
            {
                foreach (ISurfaceObject item in _items)
                {
                    if (item.IsDragging)
                    {
                        return true;
                    }
                }

                return false;
            }
        }        

        public RectangleF GetItemBounds(ISurfaceObject item)
        {
            return _bounds.GetBoundsFor(item);
        }

        public void UpdateBounds(ISurfaceObject item, RectangleF rectangleF)
        {
            _bounds.UpdateBounds(item, rectangleF);
        }

        public IList<ISurfaceObject> Selection
        {
            get
            {
                return new List<ISurfaceObject>(_items.Where(i => i.State == BaseItemState.Selected));
            }
            set
            {
                foreach (ISurfaceObject item in _items)
                {
                    if (value.Contains(item))
                    {
                        item.Selected = true;
                    }
                    else
                    {
                        if (item.Selected)
                        {
                            item.Selected = false;
                        }
                    }
                }
            }
        }

        void item_SelectionStateChanged(object sender, EventArgs e)
        {
            if (SelectionChanged != null)
            {
                SelectionChanged(this, EventArgs.Empty);
            }
        }

        private void FireCollectionChangedEvent()
        {
            if (CollectionChanged != null)
            {
                CollectionChanged(this, EventArgs.Empty);
            }
        }

        public event EventHandler SelectionChanged;

        public event EventHandler CollectionChanged;
        
    }
}
